home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / store2.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  32KB  |  1,233 lines

  1. /*
  2.  * store2.c: store code, entering, command interpreter, buying, selling 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include "constant.h"
  12. #include "config.h"
  13. #include "types.h"
  14. #include "externs.h"
  15.  
  16. #ifdef USG
  17. #ifndef ATARIST_MWC
  18. #include <string.h>
  19. #endif
  20. #else
  21. #ifndef VMS
  22. #include <strings.h>
  23. #endif
  24. #endif
  25.  
  26. #ifndef linux
  27. long                atol();
  28. #endif
  29.  
  30. static const char        *comment1[14] = {
  31.     "Done! ", "Accepted! ", "Fine. ", "Agreed! ", "Ok. ", "Taken! ",
  32.     "You drive a hard bargain, but taken. ",
  33.     "You'll force me bankrupt, but it's a deal. ", "Sigh.  I'll take it. ",
  34.     "My poor sick children may starve, but done! ", "Finally!  I accept. ",
  35.     "Robbed again. ", "A pleasure to do business with you! ",
  36.     "My spouse will skin me, but accepted. "
  37. };
  38.  
  39. static const char        *comment2a[3] = {
  40.     "%A2 is my final offer; take it or leave it.",
  41.     "I'll give you no more than %A2.",
  42.     "My patience grows thin.  %A2 is final."
  43. };
  44.  
  45. static const char        *comment2b[16] = {
  46.     "%A1 for such a fine item?  HA!  No less than %A2.",
  47.     "%A1 is an insult!  Try %A2 gold pieces.",
  48.     "%A1?!?  Go try Londis instead!",
  49.     "Why, I'll take no less than %A2 gold pieces.",
  50.     "Ha!  No less than %A2 gold pieces.",
  51.     "Thou knave!  No less than %A2 gold pieces.",
  52.     "%A1 is far too little, how about %A2?",
  53.     "I paid more than %A1 for it myself, try %A2.",
  54.     "%A1 my arse!  How about %A2 gold pieces?",
  55.     "As scrap this would bring %A1.  Try %A2 in gold.",
  56.     "May the fleas of 1000 orcs molest you.  I want %A2.",
  57.     "My mother you can get for %A1, this costs %A2.",
  58.     "May your most favourite parts go mouldy!  I want %A2 in gold!",
  59.     "Sell this for such a pittance?  Give me %A2 gold.",
  60.     "May Morgoth find you tasty!  %A2 gold pieces?",
  61.     "Your mother was a Troll/Orc/Elf!  %A2 or I'll tell."
  62. };
  63.  
  64. static const char        *comment3a[3] = {
  65.     "I'll pay no more than %A1; take it or leave it.",
  66.     "You'll get no more than %A1 from me.",
  67.     "%A1 and that's final."
  68. };
  69.  
  70. static const char        *comment3b[15] = {
  71.     "%A2 for that piece of junk?  No more than %A1.",
  72.     "For %A2 I could own ten of those.  Try %A1.",
  73.     "%A2?  NEVER!  %A1 is more like it.",
  74.     "Let's be reasonable...NOT! How about %A1 gold pieces?",
  75.     "%A1 gold for that! That's you, that is!.",
  76.     "%A1 gold pieces and be thankful for it!",
  77.     "%A1 gold pieces and not a copper more.",
  78.     "%A2 gold?  HA!  %A1 is more like it.", "Try about %A1 gold.",
  79.     "I wouldn't pay %A2 for your bottom, try %A1.",
  80.     "*CHOKE* For that!?  Let's say %A1.", "How about %A1?",
  81.     "That looks war surplus!  Say %A1 gold.",
  82.     "I'll buy it as scrap for %A1.",
  83.     "%A2 is too much, let us say %A1 gold."
  84. };
  85.  
  86. static const char        *comment4a[5] = {
  87.     "ENOUGH!  You have abused me once too often!",
  88.     "THAT DOES IT!  You shall waste my time no more!",
  89.     "This is getting nowhere.  I'm going to Londis!",
  90.     "BAHAHAHAHAHA!  No more shall you insult me!",
  91.     "Begone!  I have had enough abuse for one day."
  92. };
  93.  
  94. static const char        *comment4b[5] = {
  95.     "Out of my place!", "out... Out... OUT!!!", "Come back tomorrow.",
  96.     "Leave my place.  Begone!", "Come back when thou art richer."
  97. };
  98.  
  99. static const char        *comment5[10] = {
  100.     "You will have to do better than that!", "That's an insult!",
  101.     "Do you wish to do business or not?", "Hah!  Try again.",
  102.     "Ridiculous!", "You've got to be kidding!", "You'd better be kidding!",
  103.     "You try my patience.", "I don't hear you.",
  104.     "Hmmm, nice weather we're having."
  105. };
  106.  
  107. static const char        *comment6[5] = {
  108.     "I must have heard you wrong.", "What was that?",
  109.     "I'm sorry, say that again.", "What did you say?",
  110.     "Sorry, what was that again?"
  111. };
  112.  
  113.  
  114. /* Lets do all prototypes correctly.... -CWS */
  115. #ifndef NO_LINT_ARGS
  116. #ifdef __STDC__
  117. static void prt_comment2(int32, int32, int);
  118. static void prt_comment3(int32, int32, int);
  119. static void haggle_commands(int);
  120. static void display_inventory(int, int);
  121. static void display_cost(int, int);
  122. static void display_store(int, int);
  123. static int get_store_item(int *, const char *, int, int);
  124. static int increase_insults(int);
  125. static void decrease_insults(int);
  126. static int haggle_insults(int);
  127. static int get_haggle(const char *, int32 *, int, int32, int);
  128. static int receive_offer(int, const char *, int32 *, int32, int, int, int32, int);
  129. static int purchase_haggle(int, int32 *, inven_type *);
  130. static int sell_haggle(int, int32 *, inven_type *);
  131. static int store_purchase(int, int *);
  132. static int store_sell(int, int *);
  133. #else
  134. static void prt_comment2();
  135. static void prt_comment3();
  136. static void haggle_commands();
  137. static void display_inventory();
  138. static void display_cost();
  139. static void display_store();
  140. static int  get_store_item();
  141. static int  increase_insults();
  142. static void decrease_insults();
  143. static int  haggle_insults();
  144. static int  get_haggle();
  145. static int  receive_offer();
  146. static int  purchase_haggle();
  147. static int  sell_haggle();
  148. static int  store_purchase();
  149. static int  store_sell();
  150. #endif
  151.  
  152. static void prt_comment1();
  153. static void prt_comment4();
  154. static void prt_comment5();
  155. static void prt_comment6();
  156. static void display_commands();
  157. static void store_prt_gold();
  158. #endif
  159.  
  160. /* Comments vary.                    -RAK-     */
  161. /* Comment one : Finished haggling                 */
  162. static void 
  163. prt_comment1()
  164. {
  165.     msg_print(comment1[randint(14) - 1]);
  166. }
  167.  
  168.  
  169. /* %A1 is offer, %A2 is asking.         */
  170. static void 
  171. prt_comment2(offer, asking, final)
  172. int32 offer, asking;
  173. int   final;
  174. {
  175.     vtype comment;
  176.  
  177.     if (final > 0)
  178.     (void)strcpy(comment, comment2a[randint(3) - 1]);
  179.     else
  180.     (void)strcpy(comment, comment2b[randint(16) - 1]);
  181.  
  182.     insert_lnum(comment, "%A1", offer, FALSE);
  183.     insert_lnum(comment, "%A2", asking, FALSE);
  184.     msg_print(comment);
  185. }
  186.  
  187.  
  188. static void 
  189. prt_comment3(offer, asking, final)
  190.     int32 offer, asking;
  191.     int   final;
  192. {
  193.     vtype comment;
  194.  
  195.     if (final > 0)
  196.     (void)strcpy(comment, comment3a[randint(3) - 1]);
  197.     else
  198.     (void)strcpy(comment, comment3b[randint(15) - 1]);
  199.  
  200.     insert_lnum(comment, "%A1", offer, FALSE);
  201.     insert_lnum(comment, "%A2", asking, FALSE);
  202.     msg_print(comment);
  203. }
  204.  
  205.  
  206. /* Kick 'da bum out.                    -RAK-     */
  207. static void 
  208. prt_comment4()
  209. {
  210.     register int tmp;
  211.  
  212.     tmp = randint(5) - 1;
  213.     msg_print(comment4a[tmp]);
  214.     msg_print(comment4b[tmp]);
  215. }
  216.  
  217.  
  218. static void 
  219. prt_comment5()
  220. {
  221.     msg_print(comment5[randint(10) - 1]);
  222. }
  223.  
  224.  
  225. static void 
  226. prt_comment6()
  227. {
  228.     msg_print(comment6[randint(5) - 1]);
  229. }
  230.  
  231.  
  232. /* Displays the set of commands                -RAK-     */
  233. static void 
  234. display_commands()
  235. {
  236.     prt("You may:", 20, 0);
  237.     if (is_home) {
  238.     prt(" g) Get an item.               b) Browse through your home.", 21, 0);
  239.     prt(" d) Drop an item.              i/e/t/w/x) Inventory/Equipment Lists.",
  240.         22, 0);
  241.     prt("ESC) Exit from your home.      ^R) Redraw the screen.", 23, 0);
  242.     } else {
  243.     prt(" p) Purchase an item.          b) Browse store's inventory.", 21, 0);
  244.     prt(" s) Sell an item.              i/e/t/w/x) Inventory/Equipment Lists.",
  245.         22, 0);
  246.     prt("ESC) Exit from Building.       ^R) Redraw the screen.", 23, 0);
  247.     }
  248. }
  249.  
  250.  
  251. /* Displays the set of commands                -RAK-     */
  252. static void 
  253. haggle_commands(typ)
  254. int typ;
  255. {
  256.     if (typ == -1)
  257.     prt("Specify an asking-price in gold pieces.", 21, 0);
  258.     else
  259.     prt("Specify an offer in gold pieces.", 21, 0);
  260.     prt("ESC) Quit Haggling.", 22, 0);
  261.     erase_line(23, 0);           /* clear last line */
  262. }
  263.  
  264. /* Displays a store's inventory                -RAK-     */
  265. static void 
  266. display_inventory(store_num, start)
  267. int store_num, start;
  268. {
  269.     register store_type *s_ptr;
  270.     register inven_type *i_ptr;
  271.     register int         i, j, stop;
  272.     bigvtype             out_val1, out_val2;
  273.     int32                x;
  274.  
  275.     s_ptr = &store[store_num];
  276.     i = (start % 12);
  277.     stop = ((start / 12) + 1) * 12;
  278.     if (stop > s_ptr->store_ctr)
  279.     stop = s_ptr->store_ctr;
  280.     while (start < stop) {
  281.     i_ptr = &s_ptr->store_inven[start].sitem;
  282.     x = i_ptr->number;
  283.     if (!is_home) {
  284.         if ((i_ptr->subval >= ITEM_SINGLE_STACK_MIN)
  285.         && (i_ptr->subval <= ITEM_SINGLE_STACK_MAX))
  286.         i_ptr->number = 1;
  287.     }
  288.     objdes(out_val1, i_ptr, TRUE);
  289.     i_ptr->number = x;
  290.     (void)sprintf(out_val2, "%c) %s", 'a' + i, out_val1);
  291.     prt(out_val2, i + 5, 0);
  292.     if (!is_home) {
  293.         x = s_ptr->store_inven[start].scost;
  294.         if (x < 0) {
  295.         int32               value = (int32)(-x);
  296.         
  297.         value = value * chr_adj() / 100;
  298.         if (value <= 0)
  299.             value = 1;
  300.         (void)sprintf(out_val2, "%9ld", (long) value);
  301.         } else {
  302.         (void)sprintf(out_val2, "%9ld [Fixed]", (long) x);
  303.         }
  304.         prt(out_val2, i + 5, 59);
  305.     }
  306.     i++;
  307.     start++;
  308.     }
  309.     if (i < 12)
  310.     for (j = 0; j < (11 - i + 1); j++)
  311.         erase_line(j + i + 5, 0);    /* clear remaining lines */
  312.     if (s_ptr->store_ctr > 12)
  313.     put_buffer("- cont. -", 17, 60);
  314.     else
  315.     erase_line(17, 60);
  316. }
  317.  
  318.  
  319. /* Re-displays only a single cost            -RAK-     */
  320. static void 
  321. display_cost(store_num, pos)
  322. int store_num, pos;
  323. {
  324.     register int         i;
  325.     register int32       j;
  326.     vtype                out_val;
  327.     register store_type *s_ptr;
  328.  
  329.     s_ptr = &store[store_num];
  330.     i = (pos % 12);
  331.     if (s_ptr->store_inven[pos].scost < 0) {
  332.     j = (- (s_ptr->store_inven[pos]).scost);
  333.     j = j * chr_adj() / 100;
  334.     (void)sprintf(out_val, "%ld", (long) j);
  335.     } else
  336.     (void)sprintf(out_val, "%9ld [Fixed]",
  337.               (long) (s_ptr->store_inven[pos]).scost);
  338.     prt(out_val, i + 5, 59);
  339. }
  340.  
  341.  
  342. /* Displays players gold                    -RAK-     */
  343. static void 
  344. store_prt_gold()
  345. {
  346.     vtype out_val;
  347.  
  348.     (void)sprintf(out_val, "Gold Remaining : %ld", (long)py.misc.au);
  349.     prt(out_val, 18, 17);
  350. }
  351.  
  352.  
  353. /* Displays store                    -RAK-     */
  354. static void 
  355. display_store(store_num, cur_top)
  356. int store_num, cur_top;
  357. {
  358.     register store_type *s_ptr;
  359.  
  360.     s_ptr = &store[store_num];
  361.     clear_screen();
  362.     put_buffer(owners[s_ptr->owner].owner_name, 3, 9);
  363.     put_buffer("Item", 4, 3);
  364.     if (!is_home) {
  365.     put_buffer("Asking Price", 4, 60);
  366.     store_prt_gold();
  367.     }
  368.     display_commands();
  369.     display_inventory(store_num, cur_top);
  370. }
  371.  
  372.  
  373. /* Get the ID of a store item and return it's value    -RAK-     */
  374. static int 
  375. get_store_item(com_val, pmt, i, j)
  376. int         *com_val;
  377. const char  *pmt;
  378. register int i, j;
  379. {
  380.     char         command;
  381.     vtype        out_val;
  382.     register int flag;
  383.  
  384.     *com_val = (-1);
  385.     flag = FALSE;
  386.     (void)sprintf(out_val, "(Items %c-%c, ESC to exit) %s", i + 'a', j + 'a', pmt);
  387.     while (get_com(out_val, &command)) {
  388.     command -= 'a';
  389.     if (command >= i && command <= j) {
  390.         flag = TRUE;
  391.         *com_val = command;
  392.         break;
  393.     }
  394.     bell();
  395.     }
  396.     erase_line(MSG_LINE, 0);
  397.     return (flag);
  398. }
  399.  
  400.  
  401. /* Increase the insult counter and get angry if too many -RAK-     */
  402. static int 
  403. increase_insults(store_num)
  404. int store_num;
  405. {
  406.     register int         increase;
  407.     register store_type *s_ptr;
  408.  
  409.     increase = FALSE;
  410.     s_ptr = &store[store_num];
  411.     s_ptr->insult_cur++;
  412.     if (s_ptr->insult_cur > owners[s_ptr->owner].insult_max) {
  413.     prt_comment4();
  414.     s_ptr->insult_cur = 0;
  415.     s_ptr->good_buy = 0;
  416.     s_ptr->bad_buy = 0;
  417.     s_ptr->store_open = turn + 2500 + randint(2500);
  418.     increase = TRUE;
  419.     }
  420.     return (increase);
  421. }
  422.  
  423.  
  424. /* Decrease insults                    -RAK-     */
  425. static void 
  426. decrease_insults(store_num)
  427. int store_num;
  428. {
  429.     register store_type *s_ptr;
  430.  
  431.     s_ptr = &store[store_num];
  432.     if (s_ptr->insult_cur != 0)
  433.     s_ptr->insult_cur--;
  434. }
  435.  
  436.  
  437. /* Have insulted while haggling                -RAK-     */
  438. static int 
  439. haggle_insults(store_num)
  440. int store_num;
  441. {
  442.     register int haggle;
  443.  
  444.     haggle = FALSE;
  445.     if (increase_insults(store_num))
  446.     haggle = TRUE;
  447.     else {
  448.     prt_comment5();
  449.     msg_print(NULL);       /* force display of insult... */
  450.     }
  451.     return (haggle);
  452. }
  453.  
  454.  
  455. static int 
  456. get_haggle(comment, new_offer, num_offer, price, final)
  457. const char *comment;
  458. int32      *new_offer;
  459. int         num_offer;
  460. int32       price;
  461. int         final;
  462. {
  463.     register int32      i;
  464.     vtype               out_val;
  465.     char                buf[100];
  466.     register int        flag, clen;
  467.     register char      *p;
  468.     static int32        last_inc = 0L;
  469.     int                 inc = FALSE;
  470.  
  471.     flag = TRUE;
  472.     if (last_inc && !final)
  473.     (void)sprintf(buf, "%s [%c%ld] ", comment, (last_inc < 0) ? '-' : '+',
  474.               (last_inc < 0) ? (long)-last_inc : (long)last_inc);
  475.     else
  476.     (void)sprintf(buf, "%s [accept] ", comment);
  477.     clen = strlen(buf);
  478.     i = 0;
  479.     do {
  480.     prt(buf, 0, 0);
  481.     if (!get_string(out_val, 0, clen, 40))
  482.         flag = FALSE, last_inc = FALSE;
  483.     i = atol(out_val);
  484.     /*
  485.      * don't allow incremental haggling, if player has not made an offer yet 
  486.      */
  487.     for (p = out_val; *p == ' '; p++);
  488.     if (flag && num_offer == 0 && (*p == '+' || *p == '-')) {
  489.         msg_print("You haven't even made your first offer yet!");
  490.         i = 0;
  491.     }
  492.     if (last_inc && !i && !final)
  493.         i = last_inc, inc = TRUE;
  494.     else if (!i)
  495.         i = price;
  496.     } while (flag && !i);
  497.     if (flag) {
  498.     for (p = out_val; *p == ' '; p++);
  499.     if (*p == '+' || *p == '-')
  500.         *new_offer += i, last_inc = i;
  501.     else if (inc)
  502.         *new_offer += i, last_inc = i;
  503.     else
  504.         *new_offer = i, last_inc = 0;
  505.     } else
  506.     erase_line(0, 0);
  507.     return (flag);
  508. }
  509.  
  510.  
  511. static int 
  512. receive_offer(store_num, comment, new_offer, last_offer,
  513.           num_offer, factor, price, final)
  514. int             store_num;
  515. const char     *comment;
  516. register int32 *new_offer, last_offer;
  517. int             num_offer, factor;
  518. int32           price;
  519. int             final;
  520. {
  521.     register int flag, receive;
  522.  
  523.     receive = 0;
  524.     flag = FALSE;
  525.     do {
  526.     if (get_haggle(comment, new_offer, num_offer, price, final)) {
  527.         if (*new_offer * factor >= last_offer * factor)
  528.         flag = TRUE;
  529.         else if (haggle_insults(store_num)) {
  530.         receive = 2;
  531.         flag = TRUE;
  532.         } else
  533.  
  534. /* new_offer rejected, reset new_offer so that incremental haggling works correctly */
  535.         *new_offer = last_offer;
  536.     } else {
  537.         receive = 1;
  538.         flag = TRUE;
  539.     }
  540.     }
  541.     while (!flag);
  542.     return (receive);
  543. }
  544.  
  545.  
  546. /* Haggling routine                    -RAK-     */
  547. static int 
  548. purchase_haggle(store_num, price, item)
  549. int         store_num;
  550. int32      *price;
  551. inven_type *item;
  552. {
  553.     int32               max_sell, min_sell, max_buy;
  554.     int32               cost, cur_ask, final_ask, min_offer;
  555.     int32               last_offer, new_offer;
  556.     int32               x1, x2, x3;
  557.     int32               min_per, max_per;
  558.     register int        flag, loop_flag;
  559.     const char         *comment;
  560.     vtype               out_val;
  561.     int                 purchase, num_offer, final_flag, final = FALSE;
  562.     register store_type *s_ptr;
  563.     register owner_type *o_ptr;
  564.  
  565.     flag = FALSE;
  566.     purchase = 0;
  567.     *price = 0;
  568.     final_flag = 0;
  569.     s_ptr = &store[store_num];
  570.     o_ptr = &owners[s_ptr->owner];
  571.     cost = sell_price(store_num, &max_sell, &min_sell, item);
  572.     max_sell = max_sell * chr_adj() / 100;
  573.     if (max_sell <= 0)
  574.     max_sell = 1;
  575.     min_sell = min_sell * chr_adj() / 100;
  576.     if (min_sell <= 0)
  577.     min_sell = 1;
  578. /* cast max_inflate to signed so that subtraction works correctly */
  579.     max_buy = cost * (200 - (int)o_ptr->max_inflate) / 100;
  580.     if (max_buy <= 0)
  581.     max_buy = 1;
  582.     min_per = o_ptr->haggle_per;
  583.     max_per = min_per * 3;
  584.     haggle_commands(1);
  585.     cur_ask = max_sell;
  586.     final_ask = min_sell;
  587.     min_offer = max_buy;
  588.     last_offer = min_offer;
  589.     new_offer = 0;
  590.     num_offer = 0;      /* this prevents incremental haggling on first try */
  591.     comment = "Asking";
  592.  
  593. /* go right to final price if player has bargained well */
  594.     if (noneedtobargain(store_num, final_ask)) {
  595.     msg_print("After a long bargaining session, you agree upon the price.");
  596.     msg_print(NULL);
  597.     if (no_haggle_flag && min_sell > 10)
  598.         min_sell *= 1.10;    /* not haggling penalty -CWS */
  599.     cur_ask = min_sell;
  600.     
  601.     }
  602.     do {
  603.     do {
  604.         loop_flag = TRUE;
  605.         (void)sprintf(out_val, "%s :  %ld", comment, (long)cur_ask);
  606.         put_buffer(out_val, 1, 0);
  607.         purchase = receive_offer(store_num, "What do you offer? ",
  608.                      &new_offer, last_offer, num_offer,
  609.                      1, cur_ask, final);
  610.         if (purchase != 0)
  611.         flag = TRUE;
  612.         else {
  613.         if (new_offer > cur_ask) {
  614.             prt_comment6();
  615.         /* rejected, reset new_offer for incremental haggling */
  616.             new_offer = last_offer;
  617.         } else if (new_offer == cur_ask) {
  618.             flag = TRUE;
  619.             *price = new_offer;
  620.         } else
  621.             loop_flag = FALSE;
  622.         }
  623.     }
  624.     while (!flag && loop_flag);
  625.     if (!flag) {
  626.         x1 = (new_offer - last_offer) * 100 / (cur_ask - last_offer);
  627.         if (x1 < min_per) {
  628.         flag = haggle_insults(store_num);
  629.         if (flag)
  630.             purchase = 2;
  631.         } else if (x1 > max_per) {
  632.         x1 = x1 * 75 / 100;
  633.         if (x1 < max_per)
  634.             x1 = max_per;
  635.         }
  636.         x2 = x1 + randint(5) - 3;
  637.         x3 = ((cur_ask - new_offer) * x2 / 100) + 1;
  638.     /* don't let the price go up */
  639.         if (x3 < 0)
  640.         x3 = 0;
  641.         cur_ask -= x3;
  642.         if (cur_ask < final_ask) {
  643.         final = TRUE;
  644.         cur_ask = final_ask;
  645.         comment = "Final Offer";
  646.         final_flag++;
  647.         if (final_flag > 3) {
  648.             if (increase_insults(store_num))
  649.             purchase = 2;
  650.             else
  651.             purchase = 1;
  652.             flag = TRUE;
  653.         }
  654.         } else if (new_offer >= cur_ask) {
  655.         flag = TRUE;
  656.         *price = new_offer;
  657.         }
  658.         if (!flag) {
  659.         last_offer = new_offer;
  660.         num_offer++;       /* enable incremental haggling */
  661.         erase_line(1, 0);
  662.         (void)sprintf(out_val, "Your last offer : %ld", (long)last_offer);
  663.         put_buffer(out_val, 1, 39);
  664.         prt_comment2(last_offer, cur_ask, final_flag);
  665.         }
  666.     }
  667.     }
  668.     while (!flag);
  669.  
  670. /* update bargaining info */
  671.     if (purchase == 0)
  672.     updatebargain(store_num, *price, final_ask);
  673.  
  674.     return (purchase);
  675. }
  676.  
  677.  
  678. /* Haggling routine                    -RAK-     */
  679. static int 
  680. sell_haggle(store_num, price, item)
  681. int         store_num;
  682. int32      *price;
  683. inven_type *item;
  684. {
  685.     int32               max_sell = 0, max_buy = 0, min_buy = 0;
  686.     int32               cost = 0, cur_ask = 0, final_ask = 0, min_offer = 0;
  687.     int32               last_offer = 0, new_offer = 0;
  688.     int32               max_gold = 0;
  689.     int32               x1, x2, x3;
  690.     int32               min_per, max_per;
  691.     register int        flag, loop_flag;
  692.     const char          *comment;
  693.     vtype               out_val;
  694.     register store_type *s_ptr;
  695.     register owner_type *o_ptr;
  696.     int                 sell, num_offer, final_flag, final = FALSE;
  697.  
  698.     flag = FALSE;
  699.     sell = 0;
  700.     *price = 0;
  701.     final_flag = 0;
  702.     s_ptr = &store[store_num];
  703.     cost = item_value(item);
  704.     if (cost < 1) {
  705.     sell = 3;
  706.     flag = TRUE;
  707.     } else {
  708.     o_ptr = &owners[s_ptr->owner];
  709.     cost = cost * (200 - chr_adj()) / 100;
  710.     cost = cost * (200 - rgold_adj[o_ptr->owner_race][py.misc.prace]) / 100;
  711.     if (cost < 1)
  712.         cost = 1;
  713.     max_sell = cost * o_ptr->max_inflate / 100;
  714.     /* cast max_inflate to signed so that subtraction works correctly */
  715.     max_buy = cost * (200 - (int)o_ptr->max_inflate) / 100;
  716.     min_buy = cost * (200 - (int)o_ptr->min_inflate) / 100;
  717.     if (min_buy < 1)
  718.         min_buy = 1;
  719.     if (max_buy < 1)
  720.         max_buy = 1;
  721.     if (min_buy < max_buy)
  722.         min_buy = max_buy;
  723.     min_per = o_ptr->haggle_per;
  724.     max_per = min_per * 3;
  725.     max_gold = o_ptr->max_cost;
  726.     }
  727.     if (!flag) {
  728.     haggle_commands(-1);
  729.     if (max_buy > max_gold) {
  730.         final_flag = 1;
  731.         final = TRUE;
  732.         comment = "Final Offer";
  733.         cur_ask = max_gold;
  734.         final_ask = max_gold;
  735.         msg_print("I am sorry, but I have not the money to afford such a fine item.");
  736.     } else {
  737.         cur_ask = max_buy;
  738.         final_ask = min_buy;
  739.         if (final_ask > max_gold)
  740.         final_ask = max_gold;
  741.         comment = "Offer";
  742.  
  743.     /* go right to final price if player has bargained well */
  744.         if (noneedtobargain(store_num, final_ask)) {
  745.         msg_print("After a long bargaining session, you agree upon the price.");
  746.         msg_print(NULL);
  747.         if (no_haggle_flag && final_ask > 10)
  748.             final_ask *= .90; /* not haggling penalty -CWS */
  749.  
  750.         cur_ask = final_ask;
  751.         }
  752.     }
  753.     min_offer = max_sell;
  754.     last_offer = min_offer;
  755.     new_offer = 0;
  756.     num_offer = 0;           /* this prevents incremental haggling on first try */
  757.     if (cur_ask < 1)
  758.         cur_ask = 1;
  759.     do {
  760.         do {
  761.         loop_flag = TRUE;
  762.         (void)sprintf(out_val, "%s :  %ld", comment, (long)cur_ask);
  763.         put_buffer(out_val, 1, 0);
  764.         sell = receive_offer(store_num, "What price do you ask? ",
  765.                      &new_offer, last_offer, num_offer,
  766.                      -1, cur_ask, final);
  767.         if (sell != 0)
  768.             flag = TRUE;
  769.         else {
  770.             if (new_offer < cur_ask) {
  771.             prt_comment6();
  772.             /* rejected, reset new_offer for incremental haggling */
  773.             new_offer = last_offer;
  774.             } else if (new_offer == cur_ask) {
  775.             flag = TRUE;
  776.             *price = new_offer;
  777.             } else
  778.             loop_flag = FALSE;
  779.         }
  780.         }
  781.         while (!flag && loop_flag);
  782.         if (!flag) {
  783.         x1 = (last_offer - new_offer) * 100 / (last_offer - cur_ask);
  784.         if (x1 < min_per) {
  785.             flag = haggle_insults(store_num);
  786.             if (flag)
  787.             sell = 2;
  788.         } else if (x1 > max_per) {
  789.             x1 = x1 * 75 / 100;
  790.             if (x1 < max_per)
  791.             x1 = max_per;
  792.         }
  793.         x2 = x1 + randint(5) - 3;
  794.         x3 = ((new_offer - cur_ask) * x2 / 100) + 1;
  795.         /* don't let the price go down */
  796.         if (x3 < 0)
  797.             x3 = 0;
  798.         cur_ask += x3;
  799.         if (cur_ask > final_ask) {
  800.             cur_ask = final_ask;
  801.             final = TRUE;
  802.             comment = "Final Offer";
  803.             final_flag++;
  804.             if (final_flag > 3) {
  805.             if (increase_insults(store_num))
  806.                 sell = 2;
  807.             else
  808.                 sell = 1;
  809.             flag = TRUE;
  810.             }
  811.         } else if (new_offer <= cur_ask) {
  812.             flag = TRUE;
  813.             *price = new_offer;
  814.         }
  815.         if (!flag) {
  816.             last_offer = new_offer;
  817.             num_offer++;   /* enable incremental haggling */
  818.             erase_line(1, 0);
  819.             (void)sprintf(out_val, "Your last bid %ld", (long)last_offer);
  820.             put_buffer(out_val, 1, 39);
  821.             prt_comment3(cur_ask, last_offer, final_flag);
  822.         }
  823.         }
  824.     }
  825.     while (!flag);
  826.     }
  827. /* update bargaining info */
  828.     if (sell == 0)
  829.     updatebargain(store_num, *price, final_ask);
  830.  
  831.     return (sell);
  832. }
  833.  
  834.  
  835. /* Buy an item from a store                -RAK-     */
  836. static int 
  837. store_purchase(store_num, cur_top)
  838. int  store_num;
  839. int *cur_top;
  840. {
  841.     int32               price;
  842.     register int        i, choice;
  843.     bigvtype            out_val, tmp_str;
  844.     register store_type *s_ptr;
  845.     inven_type          sell_obj;
  846.     register inven_record *r_ptr;
  847.     int                 item_val, item_new, purchase;
  848.  
  849.     purchase = FALSE;
  850.     s_ptr = &store[store_num];
  851. /* i == number of objects shown on screen     */
  852.     if (*cur_top == 12)
  853.     i = s_ptr->store_ctr - 1 - 12;
  854.     else if (s_ptr->store_ctr > 11)
  855.     i = 11;
  856.     else
  857.     i = s_ptr->store_ctr - 1;
  858.     if (s_ptr->store_ctr < 1) {
  859.     if (is_home)
  860.         msg_print("Your home is empty.");
  861.     else
  862.         msg_print("I am currently out of stock.");
  863.     }
  864. /* Get the item number to be bought         */
  865.     else if (get_store_item(&item_val,
  866.                 is_home ? "Which item do you want to take? " :
  867.                 "Which item are you interested in? ", 0, i)) {
  868.     item_val = item_val + *cur_top;    /* TRUE item_val     */
  869.     take_one_item(&sell_obj, &s_ptr->store_inven[item_val].sitem);
  870.     if (inven_check_num(&sell_obj)) {
  871.         if (!is_home) {
  872.         if (s_ptr->store_inven[item_val].scost > 0) {
  873.             price = s_ptr->store_inven[item_val].scost;
  874.             choice = 0;
  875.         } else
  876.             choice = purchase_haggle(store_num, &price, &sell_obj);
  877.         if (choice == 0) {
  878.             if (py.misc.au >= price) {
  879.             prt_comment1();
  880.             decrease_insults(store_num);
  881.             py.misc.au -= price;
  882.             item_new = inven_carry(&sell_obj);
  883.             i = s_ptr->store_ctr;
  884.             store_destroy(store_num, item_val, TRUE);
  885.             inventory[item_new].inscrip[0] = 0;
  886.             objdes(tmp_str, &inventory[item_new], TRUE);
  887.             (void)sprintf(out_val, "You have %s (%c)",
  888.                       tmp_str, item_new + 'a');
  889.             prt(out_val, 0, 0);
  890.             check_strength();
  891.             if (*cur_top >= s_ptr->store_ctr) {
  892.                 *cur_top = 0;
  893.                 display_inventory(store_num, *cur_top);
  894.             } else {
  895.                 r_ptr = &s_ptr->store_inven[item_val];
  896.                 if (i == s_ptr->store_ctr) {
  897.                 if (r_ptr->scost < 0) {
  898.                     r_ptr->scost = price;
  899.                     display_cost(store_num, item_val);
  900.                 }
  901.                 } else
  902.                 display_inventory(store_num, item_val);
  903.                 store_prt_gold();
  904.             }
  905.             } else {
  906.             if (increase_insults(store_num))
  907.                 purchase = TRUE;
  908.             else {
  909.                 prt_comment1();
  910.                 msg_print("Liar!  You have not the gold!");
  911.             }
  912.             }
  913.         } else if (choice == 2)
  914.             purchase = TRUE;
  915.         } else {           /* is_home... */
  916.         item_new = inven_carry(&sell_obj);
  917.         i = s_ptr->store_ctr;
  918.         store_destroy(store_num, item_val, TRUE);
  919.         objdes(tmp_str, &inventory[item_new], TRUE);
  920.         (void)sprintf(out_val, "You have %s (%c)",
  921.                   tmp_str, item_new + 'a');
  922.         prt(out_val, 0, 0);
  923.         check_strength();
  924.         if (*cur_top >= s_ptr->store_ctr) {
  925.             *cur_top = 0;
  926.             display_inventory(store_num, *cur_top);
  927.         } else {
  928.             r_ptr = &s_ptr->store_inven[item_val];
  929.  
  930. #if 0
  931.             if (i == s_ptr->store_ctr) {
  932.                 if (r_ptr->scost < 0) {
  933.                     r_ptr->scost = price;
  934.                     display_cost(store_num, item_val);
  935.                 }
  936.             } else 
  937. #endif
  938.             display_inventory(store_num, item_val);
  939.         }
  940.         }
  941.     /* Less intuitive, but looks better here than in purchase_haggle. */
  942.         display_commands();
  943.         erase_line(1, 0);
  944.     } else
  945.         prt("You cannot carry that many different items.", 0, 0);
  946.     }
  947.     return (purchase);
  948. }
  949.  
  950.  
  951. /* Sell an item to the store                -RAK-     */
  952. static int 
  953. store_sell(store_num, cur_top)
  954. int store_num, *cur_top;
  955. {
  956.     int                 item_val, item_pos;
  957.     int32               price;
  958.     bigvtype            out_val, tmp_str;
  959.     inven_type          sold_obj;
  960.     register int        sell, choice, test;
  961.  
  962.     sell = FALSE;
  963.     for (item_val = 0, test = FALSE; (!test && (item_val < inven_ctr)); item_val++)
  964.     test = (*store_buy[store_num]) (inventory[item_val].tval);
  965.     if (inven_ctr < 1)
  966.     msg_print("You aren't carrying anything.");
  967.     else if (!test)
  968.     msg_print("You have nothing that I want.");
  969.     else if (get_item(&item_val, "Which one? ", 0,
  970.               inven_ctr - 1, (store_buy[store_num]))) {
  971.     take_one_item(&sold_obj, &inventory[item_val]);
  972.     objdes(tmp_str, &sold_obj, TRUE);
  973.     if (!is_home) {
  974.         (void)sprintf(out_val, "Selling %s (%c)", tmp_str, item_val + 'a');
  975.         msg_print(out_val);
  976.     }
  977.     if ((*store_buy[store_num]) (sold_obj.tval))
  978.         if (store_check_num(&sold_obj, store_num)) {
  979.         if (!is_home) {
  980.             choice = sell_haggle(store_num, &price, &sold_obj);
  981.             if (choice == 0) {
  982.             int32               cost;
  983.             int32               real;
  984.  
  985.             prt_comment1();
  986.             decrease_insults(store_num);
  987.             py.misc.au += price;
  988.  
  989.             cost = item_value(&sold_obj);
  990.  
  991.             /* identify object in inventory to set object_ident */
  992.             identify(&item_val);
  993.             /* retake sold_obj so that it will be identified */
  994.             take_one_item(&sold_obj, &inventory[item_val]);
  995.             /* call known2 for store item, so charges/pluses are known */
  996.             known2(&sold_obj);
  997.  
  998.             real = item_value(&sold_obj);
  999.  
  1000.             inven_destroy(item_val);
  1001.             objdes(tmp_str, &sold_obj, TRUE);
  1002.             (void)sprintf(out_val, "You've sold %s. ", tmp_str);
  1003.             msg_print(out_val);
  1004.  
  1005.             if (real == 0) {
  1006.                 switch (randint(4)) {
  1007.                   case 1:
  1008.                 msg_print("You hear a shriek!");
  1009.                 break;
  1010.                   case 2:
  1011.                 msg_print("You bastard!");
  1012.                 break;
  1013.                   case 3:
  1014.                 msg_print("You hear sobs coming from the back of the store...");
  1015.                 break;
  1016.                   case 4:
  1017.                 msg_print("Arrgghh!!!!");
  1018.                 break;
  1019.                 }
  1020.             } else if (real < cost) {
  1021.                 switch (randint(3)) {
  1022.                   case 1:
  1023.                 msg_print("You hear someone swearing...");
  1024.                 break;
  1025.                   case 2:
  1026.                 msg_print("You hear mumbled curses...");
  1027.                 break;
  1028.                   case 3:
  1029.                 msg_print("The shopkeeper glares at you.");
  1030.                 break;
  1031.                 }
  1032.             } else if (real > (4 * cost)) {
  1033.                 switch (randint(4)) {
  1034.                   case 1:
  1035.                 msg_print("You hear someone jumping for joy!");
  1036.                 break;
  1037.                   case 2:
  1038.                 msg_print("Yipee!");
  1039.                 break;
  1040.                   case 3:
  1041.                 msg_print("I think I'll retire!");
  1042.                 break;
  1043.                   case 4:
  1044.                 msg_print("The shopkeeper smiles gleefully!");
  1045.                 break;
  1046.                 }
  1047.             } else if (real > cost) {
  1048.                 switch (randint(4)) {
  1049.                   case 1:
  1050.                 msg_print("You hear someone giggling");
  1051.                 break;
  1052.                   case 2:
  1053.                 msg_print("You've made my day!");
  1054.                 break;
  1055.                   case 3:
  1056.                 msg_print("What a fool!");
  1057.                 break;
  1058.                   case 4:
  1059.                 msg_print("The shopkeeper laughs loudly!");
  1060.                 break;
  1061.                 }
  1062.             }
  1063.             store_carry(store_num, &item_pos, &sold_obj);
  1064.             check_strength();
  1065.             if (item_pos >= 0) {
  1066.                 if (item_pos < 12)
  1067.                 if (*cur_top < 12)
  1068.                     display_inventory(store_num, item_pos);
  1069.                 else {
  1070.                     *cur_top = 0;
  1071.                     display_inventory(store_num, *cur_top);
  1072.                 }
  1073.                 else if (*cur_top > 11)
  1074.                 display_inventory(store_num, item_pos);
  1075.                 else {
  1076.                 *cur_top = 12;
  1077.                 display_inventory(store_num, *cur_top);
  1078.                 }
  1079.             }
  1080.             store_prt_gold();
  1081.             } else if (choice == 2)
  1082.             sell = TRUE;
  1083.             else if (choice == 3) {
  1084.             msg_print("How dare you!");
  1085.             msg_print("I will not buy that!");
  1086.             sell = increase_insults(store_num);
  1087.             }
  1088.         /* Less intuitive, but looks better here than in sell_haggle. */
  1089.             erase_line(1, 0);
  1090.             display_commands();
  1091.         } else {       /* is_home... */
  1092.         /* retake sold_obj so that it will be identified */
  1093.             take_one_item(&sold_obj, &inventory[item_val]);
  1094.             inven_destroy(item_val);
  1095.             objdes(tmp_str, &sold_obj, TRUE);
  1096.             (void)sprintf(out_val, "You drop %s", tmp_str);
  1097.             msg_print(out_val);
  1098.             store_carry(store_num, &item_pos, &sold_obj);
  1099.             check_strength();
  1100.             if (item_pos >= 0) {
  1101.             if (item_pos < 12)
  1102.                 if (*cur_top < 12)
  1103.                 display_inventory(store_num, item_pos);
  1104.                 else {
  1105.                 *cur_top = 0;
  1106.                 display_inventory(store_num, *cur_top);
  1107.                 }
  1108.             else if (*cur_top > 11)
  1109.                 display_inventory(store_num, item_pos);
  1110.             else {
  1111.                 *cur_top = 12;
  1112.                 display_inventory(store_num, *cur_top);
  1113.             }
  1114.             }
  1115.         /* Less intuitive, but looks better here than in sell_haggle. */
  1116.             erase_line(1, 0);
  1117.             display_commands();
  1118.         }
  1119.         } else {
  1120.         if (is_home)
  1121.             msg_print("Your home is full.");
  1122.         else
  1123.             msg_print("I have not the room in my store to keep it.");
  1124.         }
  1125.     else {
  1126.         if (is_home)
  1127.         msg_print("Whoops! Cock up.");
  1128.         else
  1129.         msg_print("I do not buy such items.");
  1130.     }
  1131.     }
  1132.     return (sell);
  1133. }
  1134.  
  1135.  
  1136. /* Entering a store                    -RAK-     */
  1137. void 
  1138. enter_store(store_num)
  1139. int store_num;
  1140. {
  1141.     int                  cur_top, tmp_chr;
  1142.     char                 command;
  1143.     register int         exit_flag;
  1144.     register store_type *s_ptr;
  1145.  
  1146.     s_ptr = &store[store_num];
  1147.     if (store_num == 7)
  1148.     is_home = TRUE;
  1149.     else
  1150.     is_home = FALSE;
  1151.     if (s_ptr->store_open < turn) {
  1152.     exit_flag = FALSE;
  1153.     cur_top = 0;
  1154.     display_store(store_num, cur_top);
  1155.     do {
  1156.         move_cursor(20, 9);
  1157.     /* clear the msg flag just like we do in dungeon.c */
  1158.         msg_flag = FALSE;
  1159.         if (get_com(NULL, &command)) {
  1160.         switch (command) {
  1161.           case 'b':
  1162.             if (cur_top == 0)
  1163.             if (s_ptr->store_ctr > 12) {
  1164.                 cur_top = 12;
  1165.                 display_inventory(store_num, cur_top);
  1166.             } else
  1167.                 msg_print("Entire inventory is shown.");
  1168.             else {
  1169.             cur_top = 0;
  1170.             display_inventory(store_num, cur_top);
  1171.             }
  1172.             break;
  1173.           case 'E':
  1174.           case 'e':       /* Equipment List     */
  1175.           case 'I':
  1176.           case 'i':       /* Inventory         */
  1177.           case 'T':
  1178.           case 't':       /* Take off         */
  1179.           case 'W':
  1180.           case 'w':       /* Wear             */
  1181.           case 'X':
  1182.           case 'x':       /* Switch weapon         */
  1183.             tmp_chr = py.stats.use_stat[A_CHR];
  1184.             do {
  1185.             in_store_flag = TRUE;
  1186.             inven_command(command);
  1187.             command = doing_inven;
  1188.             in_store_flag = FALSE;
  1189.             }
  1190.             while (command);
  1191.         /* redisplay store prices if charisma changes */
  1192.             if (tmp_chr != py.stats.use_stat[A_CHR])
  1193.             display_inventory(store_num, cur_top);
  1194.             free_turn_flag = FALSE;    /* No free moves here. -CJS- */
  1195.             break;
  1196.           case 'g':
  1197.             if (!is_home)
  1198.             bell();
  1199.             else
  1200.             exit_flag = store_purchase(store_num, &cur_top);
  1201.             break;
  1202.           case 'p':
  1203.             if (is_home)
  1204.             bell();
  1205.             else
  1206.             exit_flag = store_purchase(store_num, &cur_top);
  1207.             break;
  1208.           case 's':
  1209.             if (is_home)
  1210.             bell();
  1211.             else
  1212.             exit_flag = store_sell(store_num, &cur_top);
  1213.             break;
  1214.           case 'd':
  1215.             if (!is_home)
  1216.             bell();
  1217.             else
  1218.             exit_flag = store_sell(store_num, &cur_top);
  1219.             break;
  1220.           default:
  1221.             bell();
  1222.             break;
  1223.         }
  1224.         } else
  1225.         exit_flag = TRUE;
  1226.     }
  1227.     while (!exit_flag);
  1228.     /* Can't save and restore the screen, because inven_command does that. */
  1229.     draw_cave();
  1230.     } else
  1231.     msg_print("The doors are locked.");
  1232. }
  1233.